package com.sdy.healthcode.h5.task;

import com.sdy.common.utils.DateUtil;
import com.sdy.healthcode.biz.constants.RedisConstants;
import com.sdy.healthcode.biz.model.ExpertsScheduleDaily;
import com.sdy.healthcode.biz.service.ExpertsScheduleDailyService;
import com.sdy.mvc.annotation.TaskSync;
import com.sdy.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;

/**
 * 排班任务
 * 这里放在h5项目是为了保证，即使停止PC端服务，排班信息也能正常生成
 */
@Component
@Slf4j
public class ExpertsScheduleTask {
    @Autowired
    private ExpertsScheduleDailyService expertsScheduleDailyService;
    @Autowired
    private RedisLockRegistry redisLockRegistry;
    @Value("${res.app.task.schedulehistory}")
    private Boolean taskScheduleHistory;
    @Autowired
    private RedisService redisService;

    @Scheduled(cron = "20 2 0 * * ?")
    @TaskSync
    public void daily() throws InterruptedException {
        Date day = DateUtil.addDate(DateUtil.getDateBegin(new Date()), 8);
        log.info("开始生成排班信息，排班日期[{}]", DateUtil.formatDate(day));
        Lock lock = redisLockRegistry.obtain(RedisConstants.LOCK_SCHEDULE_SETTING_SAVE);
        if (!lock.tryLock(60, TimeUnit.SECONDS)) {
            log.error("排班信息生成失败！");
            return;
        }
        try {
            expertsScheduleDailyService.doDailySchedule(day);
            // 标记已排班日期
            redisService.set(RedisConstants.SCHEDULED_DATE, day);
        } finally {
            lock.unlock();
        }
        log.info("排班信息生成结束，排班日期[{}]。", DateUtil.formatDate(day));
    }

    /**
     * 初始化排班
     */
    @PostConstruct
    public void initDailySchedule() throws InterruptedException {
        Lock lock = redisLockRegistry.obtain(RedisConstants.LOCK_SCHEDULE_SETTING_SAVE);
        if (!lock.tryLock(60, TimeUnit.SECONDS)) {
            log.error("排班信息生成失败！");
            return;
        }
        try {
            Date dateBegin = DateUtil.getDateBegin(new Date());
            Integer scheduleCnt = expertsScheduleDailyService.lambdaQuery().count();
            if (scheduleCnt <= 0) {
                for (int i = 0; i < 8; i++) {
                    Date day = DateUtil.addDate(dateBegin, i + 1);
                    log.info("[补充生成]开始生成排班信息，排班日期[{}]", DateUtil.formatDate(day));
                    expertsScheduleDailyService.doDailySchedule(day);
                    log.info("[补充生成]排班信息生成结束，排班日期[{}]。", DateUtil.formatDate(day));
                    // 标记已排班日期
                    Date date = redisService.get(RedisConstants.SCHEDULED_DATE, Date.class);
                    if (date == null || date.before(day)) {
                        redisService.set(RedisConstants.SCHEDULED_DATE, day);
                    }
                }
            }
        } finally {
            lock.unlock();
        }
    }

    /**
     * 历史排班 - 开发环境执行
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    @TaskSync
    public void historySchedule() throws InterruptedException {
        if (taskScheduleHistory) {
            initDailySchedule();
        }
    }
}
